---
title: Routing
description: Learn how to integrate client side routing into your HeroUI application.
---

# Routing

HeroUI Components such as [Tabs](/docs/components/tabs), [Listbox](/docs/components/listbox), [Dropdown](/docs/components/dropdown) and many others offer
the flexibility to be rendered as **HTML links**.

<CarbonAd />

## Introduction

By default, links perform native browser navigation when they are interacted with. However, many apps and
frameworks use client side routers to avoid a full page reload when navigating between pages.

The `HeroUIProvider` component configures all HeroUI components within it to navigate using the client side
router you provide.

Set this up once in the `root` of your app, and any HeroUI component with the `href` prop will automatically navigate
using your router.

## HeroUIProvider Setup

The `HeroUIProvider` component accepts `navigate` and `useHref` props. `navigate` is a router function for client-side
navigation, while `useHref` optionally converts router hrefs to native HTML hrefs. Here's the pattern:

```jsx
import * as React from "react";

import {HeroUIProvider} from "@heroui/react";
import {useNavigate, useHref} from "your-router";

function App() {
  const navigate = useNavigate();

  return (
    <HeroUIProvider navigate={navigate} useHref={useHref}>
      <YourApplication />
    </HeroUIProvider>
  );
}
```

<Spacer y={2} />

> **Note**: Framework-specific examples are shown below.

### Router Options

All `HeroUI` link components accept a `routerOptions` prop that passes options to the router's navigate function for
controlling behavior like scrolling and history navigation.

```jsx
<DropdownItem href="/login" routerOptions={{replace: true}}>
  {/* ...*/}
</DropdownItem>
```

When using TypeScript, you can configure the RouterConfig type globally so that all link components have auto
complete and type safety using a type provided by your router.

```tsx
import type {RouterOptions} from "your-router";

declare module "@react-types/shared" {
  interface RouterConfig {
    routerOptions: RouterOptions;
  }
}
```

<Spacer y={2} />

## Next.js

#### App Router

Go to your `app/providers.tsx` or `app/providers.jsx` (create it if it doesn't exist) and add the
`useRouter` hook from `next/navigation`, it returns a router object that can be used to perform navigation.

> Check the [Next.js docs](https://nextjs.org/docs/app/api-reference/functions/use-router) for more details.

<Steps>

#### Add the `useRouter`

```tsx {15}
// app/providers.tsx
"use client";

import {useRouter} from "next/navigation";
import {HeroUIProvider} from "@heroui/react";

// Only if using TypeScript
declare module "@react-types/shared" {
  interface RouterConfig {
    routerOptions: NonNullable<Parameters<ReturnType<typeof useRouter>["push"]>[1]>;
  }
}

export function Providers({children}: {children: React.ReactNode}) {
  const router = useRouter();

  return <HeroUIProvider navigate={router.push}>{children}</HeroUIProvider>;
}
```

#### Add Provider to Root

Now, Go to your `root` layout page and wrap it with the `HeroUIProvider`:

```tsx {8}
// app/layout.tsx
import {Providers} from "./providers";

export default function RootLayout({children}: {children: React.ReactNode}) {
  return (
    <html lang="en" className="dark">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}
```

> **Note**: Skip this step if you already set up the `HeroUIProvider` in your app.

#### Next.js Base Path (Optional)

If you are using the Next.js [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) setting,
you'll need to configure an environment variable to access it.

```js
// next.config.js
const basePath = "...";
const nextConfig = {
  basePath,
  env: {
    BASE_PATH: basePath,
  },
};
```

Then, provide a custom `useHref` function to prepend it to the href for all links.

```tsx {9,12}
// app/providers.tsx
"use client";

import {useRouter} from "next/navigation";
import {HeroUIProvider} from "@heroui/react";

export function Providers({children}: {children: React.ReactNode}) {
  const router = useRouter();
  const useHref = (href: string) => process.env.BASE_PATH + href;

  return (
    <HeroUIProvider navigate={router.push} useHref={useHref}>
      {children}
    </HeroUIProvider>
  );
}
```

</Steps>

### Pages Router

Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook
from `next/router`, it returns a router object that can be used to perform navigation.

```tsx
// pages/_app.tsx
import type {AppProps} from "next/app";
import {type NextRouter, useRouter} from "next/router";
import {HeroUIProvider} from "@heroui/react";

declare module "@react-types/shared" {
  interface RouterConfig {
    routerOptions: NonNullable<
      Parameters<NextRouter['push']>[2]
    >;
  }
}

function MyApp({Component, pageProps}: AppProps) {
  const router = useRouter();

  return (
    <HeroUIProvider navigate={router.push}>
      <Component {...pageProps} />
    </HeroUIProvider>
  );
}

export default MyApp;
```

When using the [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) configuration option, 
provide a `useHref` option to the router passed to Provider to prepend it to links automatically.

```tsx {8}
// pages/_app.tsx
import type {AppProps} from "next/app";
import {HeroUIProvider} from "@heroui/react";
import {useRouter} from "next/router";

function MyApp({Component, pageProps}: AppProps) {
  const router = useRouter();
  const useHref = (href: string) => router.basePath + href;

  return (
    <HeroUIProvider navigate={router.push} useHref={useHref}>
      <Component {...pageProps} />
    </HeroUIProvider>
  );
}

export default MyApp;
```

## React Router

Use the `useNavigate` hook from `react-router-dom` to get the `navigate` function for routing. The `useHref` hook can be used with React Router's `basename` option.

Make sure to place the component using these hooks inside `BrowserRouter` and keep `<Routes>` within `HeroUIProvider`. Here's how to set it up in your App component:

```tsx
// App.tsx or App.jsx
import type {NavigateOptions} from "react-router-dom";

import {BrowserRouter, useNavigate, useHref} from "react-router-dom";
import {HeroUIProvider} from "@heroui/react";

declare module "@react-types/shared" {
  interface RouterConfig {
    routerOptions: NavigateOptions;
  }
}

function App() {
  const navigate = useNavigate();

  return (
    <HeroUIProvider navigate={navigate} useHref={useHref}>
      {/* Your app here... */}
      <Routes>
        <Route path="/" element={<HomePage />} />
        {/* ... */}
      </Routes>
    </HeroUIProvider>
  );
}

// main.tsx or main.jsx
ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
);
```

Ensure that the component that calls `useNavigate` and renders `HeroUIProvider` is inside the router
component (e.g. `BrowserRouter`) so that it has access to React Router's internal context. The React Router `<Routes>`
element should also be defined inside `HeroUIProvider` so that links inside the rendered routes have access
to the router.

## Remix

Remix uses React Router under the hood, so the same `useNavigate` and `useHref` hook described above also works in Remix
apps. `HeroUIProvider` should be rendered at the `root` of each page that includes HeroUI components, or in
`app/root.tsx` to add it to all pages. See the [Remix docs](https://remix.run/docs/en/main/file-conventions/root)
for more details.

```tsx
// app/root.tsx
import type {NavigateOptions} from 'react-router-dom';

import {useNavigate, useHref, Outlet} from "@remix-run/react";
import {HeroUIProvider} from "@heroui/react";

declare module "@react-types/shared" {
  interface RouterConfig {
    routerOptions: NavigateOptions;
  }
}

export default function App() {
  const navigate = useNavigate();

  return (
    <html lang="en">
      <head>{/* ... */}</head>
      <body>
        <HeroUIProvider navigate={navigate} useHref={useHref}>
          <Outlet />
        </HeroUIProvider>
        {/* ... */}
      </body>
    </html>
  );
}
```

## TanStack

To use [TanStack Router](https://tanstack.com/router/latest), use the [createLink](https://tanstack.com/router/latest/docs/framework/react/guide/custom-link) function to wrap each HeroUI component as a link. `RouterProvider` is not needed.

```tsx
// app/root.tsx
import {createLink} from '@tanstack/react-router';
import {Link as HeroUILink, DropdownItem} from '@heroui/react';


import {useRouter} from '@tanstack/react-router';
import {HeroUIProvider} from "@heroui/react";


declare module "@react-types/shared" {
  interface RouterConfig {
    href: ToOptions['to'];
    routerOptions: Omit<NavigateOptions, keyof ToOptions>;
  }
}

function RootRoute() {
  let router = useRouter();

  return (
    <HeroUIProvider
      navigate={(to, options) => router.navigate({to, ...options})}
      useHref={(to) => router.buildLocation({to}).href}
    >
      {/* You app here... */}
    </HeroUIProvider>
  );
}
```

## Usage examples

Now that you have set up the `HeroUIProvider` in your app, you can use the `href` prop in the `Tabs`,
`Listbox` and `Dropdown` items to navigate between pages.

The [Link](/docs/components/link) component will also use the `navigate` function from the
`HeroUIProvider` to navigate between pages.

```jsx
import {
  Tabs,
  Tab,
  Listbox,
  ListboxItem,
  Dropdown,
  DropdownTrigger,
  DropdownMenu,
  DropdownItem,
  Button,
  Link,
} from "@heroui/react";

function App() {
  return (
    <>
      <Tabs aria-label="Navigation">
        <Tab key="home" href="/home">
          Home
        </Tab>
        <Tab key="about" href="/about">
          About
        </Tab>
      </Tabs>
      <Listbox aria-label="Navigation">
        <ListboxItem key="home" href="/home">
          Home
        </ListboxItem>
        <ListboxItem key="about" href="/about">
          About
        </ListboxItem>
      </Listbox>
      <Dropdown>
        <DropdownTrigger>
          <Button>Open</Button>
        </DropdownTrigger>
        <DropdownMenu aria-label="Navigation">
          <DropdownItem key="home" href="/home">
            Home
          </DropdownItem>
          <DropdownItem key="about" href="/about">
            About
          </DropdownItem>
        </DropdownMenu>
      </Dropdown>
      <Link href="/home">Home</Link>
      <Link href="/about">About</Link>
    </>
  );
}
```
